cmake_minimum_required(VERSION 3.1)
project(TGFX)

#set(CMAKE_VERBOSE_MAKEFILE ON)
include(../vendor_tools/vendor.cmake)

# Options for building tgfx
option(TGFX_USE_METAL "Allow use of Metal as GPU backend" OFF)
option(TGFX_USE_VULKAN "Allow use of Vulkan as GPU backend" OFF)
option(TGFX_USE_QT "Allow use of QT frameworks as GPU backend" OFF)

if (IOS OR MACOS)
    option(TGFX_USE_CORE_GRAPHICS "Allow use of CoreGraphics as vector backend" ON)
endif ()

if (IOS OR WEB)
    option(TGFX_USE_WEBP_DECODE "Enable embedded WEBP decoding support" ON)
elseif (NOT ANDROID)
    option(TGFX_USE_PNG_DECODE "Enable embedded PNG decoding support" ON)
    option(TGFX_USE_PNG_ENCODE "Enable embedded PNG encoding support" ON)
    option(TGFX_USE_JPEG_DECODE "Enable embedded JPEG decoding support" ON)
    option(TGFX_USE_JPEG_ENCODE "Enable embedded JPEG encoding support" ON)
    option(TGFX_USE_WEBP_DECODE "Enable embedded WEBP decoding support" ON)
    option(TGFX_USE_WEBP_ENCODE "Enable embedded WEBP encoding support" ON)
endif ()

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
cmake_policy(SET CMP0063 NEW)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)

if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    add_definitions(-Werror -Wall -Wextra -Weffc++ -pedantic -Werror=return-type)
endif ()

if (MSVC)
    add_compile_options("/utf-8")
    add_definitions(-DNOMINMAX -D_USE_MATH_DEFINES)
endif (MSVC)

# Sets flags
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
    add_definitions(-DDEBUG)
    #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -g -O1")
endif ()

# collects tgfx common files.
set(TGFX_INCLUDES ./ include src)
list(APPEND TGFX_INCLUDES ../ ../include ../src)
file(GLOB_RECURSE TGFX_FILES src/core/*.*)
file(GLOB COMMON_FILES
        src/gpu/*.*
        src/image/*.*
        src/platform/*.*
        src/raster/*.*)
list(APPEND TGFX_FILES ${COMMON_FILES})

if (TGFX_USE_PNG_DECODE)
    add_definitions(-DTGFX_USE_PNG_DECODE)
    set(TGFX_USE_PNG ON)
endif ()

if (TGFX_USE_PNG_ENCODE)
    add_definitions(-DTGFX_USE_PNG_ENCODE)
    set(TGFX_USE_PNG ON)
endif ()

if (TGFX_USE_JPEG_DECODE)
    add_definitions(-DTGFX_USE_JPEG_DECODE)
    set(TGFX_USE_JPEG ON)
endif ()

if (TGFX_USE_JPEG_ENCODE)
    add_definitions(-DTGFX_USE_JPEG_ENCODE)
    set(TGFX_USE_JPEG ON)
endif ()

if (TGFX_USE_WEBP_DECODE)
    add_definitions(-DTGFX_USE_WEBP_DECODE)
    set(TGFX_USE_WEBP ON)
endif ()

if (TGFX_USE_WEBP_ENCODE)
    add_definitions(-DTGFX_USE_WEBP_ENCODE)
    set(TGFX_USE_WEBP ON)
endif ()

if (TGFX_USE_JPEG)
    list(APPEND TGFX_STATIC_VENDORS libjpeg-turbo)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/image/jpeg/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    list(APPEND TGFX_INCLUDES ../third_party/out/libjpeg-turbo/${INCLUDE_ENTRY})
endif ()

if (TGFX_USE_WEBP)
    list(APPEND TGFX_STATIC_VENDORS libwebp)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/image/webp/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    list(APPEND TGFX_INCLUDES ../third_party/libwebp/src)
endif ()

if (TGFX_USE_PNG)
    list(APPEND TGFX_STATIC_VENDORS libpng)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/image/png/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    list(APPEND TGFX_INCLUDES ../third_party/out/libpng/${INCLUDE_ENTRY})
endif ()

list(APPEND TGFX_STATIC_VENDORS pathkit)
list(APPEND TGFX_INCLUDES ../third_party/pathkit)
list(APPEND TGFX_STATIC_VENDORS skcms)
list(APPEND TGFX_INCLUDES ../third_party/skcms)

add_vendor_target(TGFX STATIC_VENDORS ${TGFX_STATIC_VENDORS})
list(APPEND TGFX_STATIC_LIBS ${TGFX_VENDOR_STATIC_LIBRARIES})

# collects freetype files.
if (NOT TGFX_USE_PNG)
    # freetype has embedded libpng
    list(APPEND FREETYPE_DEFINITIONS TGFX_USE_PNG_DECODE)
endif ()

list(APPEND FREETYPE_DEFINITIONS TGFX_USE_FREETYPE)
file(GLOB_RECURSE FREETYPE_FILES src/raster/freetype/*.*)
list(APPEND FREETYPE_INCLUDES ../third_party/freetype/include)
add_vendor_target(FREETYPE STATIC_VENDORS freetype)
list(APPEND FREETYPE_STATIC_LIBS ${FREETYPE_VENDOR_STATIC_LIBRARIES})
file(GLOB_RECURSE OPENGL_FILES src/gpu/opengl/*.*)
list(APPEND EGL_INCLUDES ../third_party/swiftshader/include)

function(append_module target module)
    set(${target}_DEFINITIONS ${${target}_DEFINITIONS} ${${module}_DEFINITIONS} PARENT_SCOPE)
    set(${target}_INCLUDES ${${target}_INCLUDES} ${${module}_INCLUDES} PARENT_SCOPE)
    set(${target}_FILES ${${target}_FILES} ${${module}_FILES} PARENT_SCOPE)
    set(${target}_STATIC_LIBS ${${target}_STATIC_LIBS} ${${module}_STATIC_LIBS} PARENT_SCOPE)
    set(${target}_SHARED_LIBS ${${target}_SHARED_LIBS} ${${module}_SHARED_LIBS} PARENT_SCOPE)
endfunction()

if (TGFX_USE_QT)
    # need to set the CMAKE_PREFIX_PATH to local QT installation path, for example :
    # set(CMAKE_PREFIX_PATH /Users/username/Qt5.13.0/5.13.0/clang_64/lib/cmake)
    find_package(Qt5OpenGL REQUIRED)
    list(APPEND PLATFORM_SHARED_LIBS ${Qt5OpenGL_LIBRARIES})
    file(GLOB_RECURSE PLATFORM_FILES src/platform/mock/*.*)
    list(APPEND PLATFORM_FILES ${OPENGL_FILES})
    list(APPEND PLATFORM_FILES ${FREETYPE_FILES})
    list(APPEND PLATFORM_VENDOR_TARGETS ${FREETYPE_VENDOR_TARGET})
    append_module(PLATFORM FREETYPE)
elseif (IOS OR MACOS)
    find_library(Foundation_LIBS Foundation REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${Foundation_LIBS})
    find_library(ImageIO_LIBS ImageIO REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${ImageIO_LIBS})
    find_library(CORE_VIDEO CoreVideo)
    list(APPEND TGFX_SHARED_LIBS ${CORE_VIDEO})

    if (IOS)
        find_library(OpenGL_LIBS OpenGLES REQUIRED)
        file(GLOB_RECURSE PLATFORM_FILES src/platform/ios/*.* src/platform/apple/*.*)
    else ()
        find_library(OpenGL_LIBS OpenGL REQUIRED)
        find_library(COCOA Cocoa REQUIRED)
        list(APPEND TGFX_SHARED_LIBS ${COCOA})
        find_library(APPLICATION_SERVICES_FRAMEWORK ApplicationServices REQUIRED)
        list(APPEND TGFX_SHARED_LIBS ${APPLICATION_SERVICES_FRAMEWORK})
        file(GLOB_RECURSE PLATFORM_FILES src/platform/mac/*.* src/platform/apple/*.*)
    endif ()

    list(APPEND CORE_GRAPHICS_DEFINITIONS TGFX_USE_CORE_GRAPHICS)
    file(GLOB_RECURSE CORE_GRAPHICS_FILES src/raster/coregraphics/*.*)
    find_library(QuartzCore_LIBS QuartzCore REQUIRED)
    list(APPEND CORE_GRAPHICS_SHARED_LIBS ${QuartzCore_LIBS})
    find_library(CoreGraphics_LIBS CoreGraphics REQUIRED)
    list(APPEND CORE_GRAPHICS_SHARED_LIBS ${CoreGraphics_LIBS})
    find_library(CoreText_LIBS CoreText REQUIRED)
    list(APPEND CORE_GRAPHICS_SHARED_LIBS ${CoreText_LIBS})
    find_library(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c)
    list(APPEND CORE_GRAPHICS_SHARED_LIBS ${ICONV_LIBRARIES})
    file(GLOB_RECURSE METAL_FILES src/gpu/metal/*.*)
    find_library(METAL_SHARED_LIBS Metal REQUIRED)

    if (TGFX_USE_CORE_GRAPHICS)
        append_module(PLATFORM CORE_GRAPHICS)
    else ()
        list(APPEND PLATFORM_VENDOR_TARGETS ${FREETYPE_VENDOR_TARGET})
        append_module(PLATFORM FREETYPE)
    endif ()

    if (TGFX_USE_METAL)
        append_module(PLATFORM METAL)
    else ()
        list(APPEND PLATFORM_SHARED_LIBS ${OpenGL_LIBS})
        list(APPEND PLATFORM_DEFINITIONS GL_SILENCE_DEPRECATION)
    endif ()
elseif (ANDROID)
    find_library(LOG_LIB log REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${LOG_LIB})
    find_library(ANDROID_LIB android REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${ANDROID_LIB})
    find_library(JNIGRAPHICS_LIB jnigraphics REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${JNIGRAPHICS_LIB})
    find_library(Z_LIB z)
    list(APPEND TGFX_SHARED_LIBS ${Z_LIB})

    file(GLOB_RECURSE PLATFORM_FILES src/platform/android/*.*)
    list(APPEND PLATFORM_FILES ${OPENGL_FILES})
    list(APPEND PLATFORM_FILES ${FREETYPE_FILES})
    list(APPEND PLATFORM_VENDOR_TARGETS ${FREETYPE_VENDOR_TARGET})
    append_module(PLATFORM FREETYPE)
    find_library(EGL_LIB EGL REQUIRED)
    list(APPEND PLATFORM_SHARED_LIBS ${EGL_LIB})
    find_library(GLESV2_LIB GLESv2 REQUIRED)
    list(APPEND PLATFORM_SHARED_LIBS ${GLESV2_LIB})
else ()
    file(GLOB_RECURSE PLATFORM_FILES src/platform/mock/*.*)
    list(APPEND PLATFORM_FILES ${OPENGL_FILES})
    list(APPEND PLATFORM_FILES ${FREETYPE_FILES})
    list(APPEND PLATFORM_INCLUDES ${EGL_INCLUDES})
    list(APPEND PLATFORM_VENDOR_TARGETS ${FREETYPE_VENDOR_TARGET})
    append_module(PLATFORM FREETYPE)
endif ()

add_library(tgfx STATIC ${TGFX_VENDOR_TARGET} ${PLATFORM_VENDOR_TARGETS} ${TGFX_FILES} ${PLATFORM_FILES})
target_compile_definitions(tgfx PUBLIC ${PLATFORM_DEFINITIONS})
target_include_directories(tgfx PUBLIC ${TGFX_INCLUDES} ${PLATFORM_INCLUDES})
merge_libraries_into(tgfx ${TGFX_STATIC_LIBS} ${PLATFORM_STATIC_LIBS})
target_link_libraries(tgfx)

file(GLOB_RECURSE MOCK_FILES src/platform/mock/*.*)
list(APPEND MOCK_FILES ${OPENGL_FILES})
list(APPEND MOCK_INCLUDES ${EGL_INCLUDES})

add_library(tgfx-egl-ft STATIC ${TGFX_VENDOR_TARGET} ${FREETYPE_VENDOR_TARGET} ${TGFX_FILES} ${MOCK_FILES} ${FREETYPE_FILES})
target_compile_definitions(tgfx-egl-ft PUBLIC ${FREETYPE_DEFINITIONS})
target_include_directories(tgfx-egl-ft PUBLIC ${TGFX_INCLUDES} ${MOCK_INCLUDES} ${FREETYPE_INCLUDES})
merge_libraries_into(tgfx-egl-ft ${TGFX_STATIC_LIBS} ${FREETYPE_STATIC_LIBS})
target_link_libraries(tgfx-egl-ft)

add_library(tgfx-egl-cg STATIC ${TGFX_VENDOR_TARGET} ${FREETYPE_VENDOR_TARGET} ${TGFX_FILES} ${MOCK_FILES} ${CORE_GRAPHICS_FILES})
target_compile_definitions(tgfx-egl-cg PUBLIC ${CORE_GRAPHICS_DEFINITIONS})
target_include_directories(tgfx-egl-cg PUBLIC ${TGFX_INCLUDES} ${MOCK_INCLUDES})
merge_libraries_into(tgfx-egl-cg ${TGFX_STATIC_LIBS})
target_link_libraries(tgfx-egl-cg)